var GFIterator = Base.extend({
	constructor: function()
	{
	},
	next: function()
	{
	},
	prev: function()
	{
	},
	current: function()
	{
	},
	nullp: function()
	{
	}
});


var GFListNode = Base.extend({
	prev: null,
	next: null,
	data: null,
	constructor: function(next,prev,data)
	{
		this.data = data;
		this.prev = prev;
		this.next = next;
	}
});

var GFListIterator = GFIterator.extend({
	list: null,
	node: null,
	constructor: function(list,node)
	{
		this.list = list;
		this.node = node;
	},
	next: function()
	{
		if(this.node != null) this.node = this.node.next;
		return (this.node != null) ? true : false;
	},
	prev: function()
	{
		if(this.node != null) this.node = this.node.prev;
		return (this.node != null) ? true : false;
	},
	nullp: function()
	{
		return (this.node == null) ? true : false;
	},
	current: function()
	{
		return (this.node == null) ? null : (this.node.data);
	},
	insertbefore: function(data)
	{
		if(this.list == null) return false;
		if(this.node == null) {
			this.list.push_tail(data);
			return true;
		}
		if(this.node == this.list.head) {
			this.list.push_head(data);
			return true;
		}

		var p = new GFListNode(this.node,this.node.prev,data);
		this.node.prev = p;
		if(p.next != null) p.next.prev = p;
		if(p.prev != null) p.prev.next = p;
		this.node = p;
		this.list.count++;
		return true;
	},
	insertafter: function(data)
	{
		if(this.list == null) return false;
		if(this.node == null) {
			this.list.push_head(data);
			return true;
		}
		if(this.node == this.list.tail) {
			this.list.push_tail(data);
			return true;
		}

		var p = new GFListNode(this.node.next,this.node,data);
		this.node.next = p;
		if(p.next != null) p.next.prev = p;
		if(p.prev != null) p.prev.next = p;
		this.node = p;
		this.list.count++;
		return true;
	},
	remove: function()
	{
		var p = this.node;
		if(this.node.prev != null) this.node.prev.next = this.node.next;
		if(this.node.next != null) this.node.next.prev = this.node.prev;
		if(this.node == this.list.head) this.list.head = this.node.next;
		if(this.node == this.list.tail) this.list.tail = this.node.prev;
		this.node = this.node.next;
		delete p;
		this.list.count--;
	}
});

var GFList = Base.extend({
	head: null,
	tail: null,
	count: 0,
	constructor: function()
	{
	},
	push_head: function(data)
	{
		var p = new GFListNode(this.head,null,data);

		if(this.head != null) this.head.prev = p;
		this.head = p;
		if(this.tail == null) this.tail = this.head;
		this.count++;
	},
	push_tail: function(data)
	{
		var p = new GFListNode(null,this.tail,data);

		if(this.tail != null) this.tail.next = p;
		this.tail = p;
		if(this.head == null) this.head = this.tail;
		this.count++;
	},
	get_head: function()
	{
		if(this.head) return this.head.data;
		else null;
	},
	get_tail: function()
	{
		if(this.tail) return this.tail.data;
		else null;
	},
	pop_head: function()
	{
		var p = this.head;

		if(p == null) return false;
		if(p.next != null) p.next.prev = null;
		this.head = p.next;
		if(p == this.tail) this.tail = null;
		delete p;
		this.count--;
		return true;
	},
	pop_tail: function()
	{
		var p = this.tail;

		if(p == null) return false;
		if(p.prev != null) p.prev.next = null;
		this.tail = p.prev;
		if(p == this.head) this.head = null;
		delete p;
		this.count--;
		return true;
	},
	push: function(data) { this.push_head(data); },
	pop: function(data) { this.pop_head(data); },
	remove_all: function()
	{
		this.count = 0;
		this.head = null;
		this.tail = null;
	},
	begin: function()
	{
		return new GFListIterator(this,this.head);
	},
	end: function()
	{
		return new GFListIterator(this,this.tail);
	}
});

